package com.CST.service.impl.ys;
import com.CST.bo.YsBudgetBO;
import com.CST.common.constant.Constants;
import com.CST.dto.ys.BudgetDTO;
import com.CST.dto.ys.ExportDTO;
import com.CST.entity.cb.BdSysUser;
import com.CST.entity.ys.YsBusinessBudgetRelease;
import com.CST.mapper.cst.cb.BdSysUserMapper;
import com.CST.mapper.cst.ys.YsAccountBudgetMapper;
import com.CST.service.ys.YsAccountBudgetService;
import com.CST.util.ExcelTransfer;
import com.CST.util.HttpUtil;
import com.CST.util.PageHelperTool;
import com.CST.vo.ys.AccountHeaderVO;
import com.CST.vo.ys.BudgetRelease;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;


@Service
public class YsAccountBudgetServiceImp implements YsAccountBudgetService {
    private final YsAccountBudgetMapper mapper;

    @Autowired
    private BdSysUserMapper userMapper;

    private final ExcelTransfer<YsBusinessBudgetRelease> excelTransfer;
    public YsAccountBudgetServiceImp(YsAccountBudgetMapper mapper, ExcelTransfer<YsBusinessBudgetRelease> excelTransfer) {
        this.mapper = mapper;
        this.excelTransfer = excelTransfer;
    }



    /*
    * 查询管理预算下达数据*/
    @Override
    public BudgetRelease management(BudgetDTO dto) {
        Optional.ofNullable(dto.getStartTime())
                .orElseThrow(()->new RuntimeException("起始时间不能为空"));
        Optional.ofNullable(dto.getEndTime())
                .orElseThrow(()->new RuntimeException("截止时间不能为空"));
        Optional.ofNullable(dto.getNum())
                .orElseThrow(()->new RuntimeException("页码为空"));
        Optional.ofNullable(dto.getSize())
                .orElseThrow(()->new RuntimeException("页大小为空"));
        String [] st = dto.getStartTime().split("-");
        String [] end = dto.getEndTime().split("-");
        if(!st[0].equals(end[0])){
            throw  new RuntimeException("年份不能跨越");
        }
        dto.setYear(Integer.valueOf(st[0]));
        dto.setStart(Integer.valueOf(st[1]));
        dto.setEnd(Integer.valueOf(end[1]));
        // 部门隔离
        BdSysUser user = userMapper.getUserById(HttpUtil.getRequestHeaderInfo(Constants.USER_ID));
        // todo  临时权限
        if (!"ALL".equals(user.getDeptCode())){
            dto.setDeptCode(user.getDeptCode());
        }

        //过滤数据
        List<YsBudgetBO> budgetBOList = mapper.getAllManagement(dto);//获取所有当前年的数据
        Map<String,LinkedHashMap<String,Object>> map = new HashMap<>();
        budgetBOList.forEach(t->{
            if(map.containsKey(t.getSubjectCode())){
                if(!map.get(t.getSubjectCode()).containsValue(t.getDepartmentName())){
                    //拼接部门名称
                    String newName = map.get(t.getSubjectCode()).get("departmentName") +","+t.getDepartmentName();
                    map.get(t.getSubjectCode()).put("departmentName", newName);
                }
            }else{
                map.put(t.getSubjectCode(),filterData(dto.getStart(), dto.getEnd(), t));
            }
        });
        List<LinkedHashMap<String, Object>> linkedHashMaps = new ArrayList<>(map.values());
        LinkedHashMap<String, BigDecimal> tableSum = calculate(linkedHashMaps, dto.getStart(), dto.getEnd());

        PageInfo<LinkedHashMap<String,Object>> pageInfo = PageHelperTool.excutePageInfo(linkedHashMaps, dto.getNum(),dto.getSize());
        List<AccountHeaderVO> tableHeader = generateTableHeader(dto.getStart(), dto.getEnd());
        BudgetRelease budget = new BudgetRelease();
        budget.setTableSum(tableSum);
        budget.setTableHeader(tableHeader);
        budget.setTableData(pageInfo);
        return budget;
    }

    @Override
    public void exportExcel3(HttpServletResponse response) {
        excelTransfer.exportExcel(response, mapper.selectNew(), "业务预算下达数据模板", "sheet",
                YsBusinessBudgetRelease.class);
    }

    private void selectMonth(Integer start,Integer end,LinkedHashMap<String,Object> map,YsBudgetBO budget){
        for(int i=start;i<=end;i++){
            switch (i){
                case 1:
                    map.put("month1",1);
                    map.put("sx1",budget.getSan14());
                    map.put("xg1",budget.getXu14());
                    map.put("sum1",budget.getAll14());
                    break;
                case 2:
                    map.put("month2",2);
                    map.put("sx2",budget.getSan24());
                    map.put("xg2",budget.getXu24());
                    map.put("sum2",budget.getAll24());
                    break;
                case 3:
                    map.put("month3",3);
                    map.put("sx3",budget.getSan34());
                    map.put("xg3",budget.getXu34());
                    map.put("sum3",budget.getAll34());
                    break;
                case 4:
                    map.put("month4",4);
                    map.put("sx4",budget.getSan44());
                    map.put("xg4",budget.getXu44());
                    map.put("sum4",budget.getAll44());
                    break;
                case 5:
                    map.put("month5",5);
                    map.put("sx5",budget.getSan54());
                    map.put("xg5",budget.getXu54());
                    map.put("sum5",budget.getAll54());
                    break;
                case 6:
                    map.put("month6",6);
                    map.put("sx6",budget.getSan64());
                    map.put("xg6",budget.getXu64());
                    map.put("sum6",budget.getAll64());
                    break;
                case 7:
                    map.put("month7",7);
                    map.put("sx7",budget.getSan74());
                    map.put("xg7",budget.getXu74());
                    map.put("sum7",budget.getAll74());
                    break;
                case 8:
                    map.put("month8",8);
                    map.put("sx8",budget.getSan84());
                    map.put("xg8",budget.getXu84());
                    map.put("sum8",budget.getAll84());
                    break;
                case 9:
                    map.put("month9",9);
                    map.put("sx9",budget.getSan94());
                    map.put("xg9",budget.getXu94());
                    map.put("sum9",budget.getAll94());
                    break;
                case 10:
                    map.put("month10",10);
                    map.put("sx10",budget.getSan104());
                    map.put("xg10",budget.getXu104());
                    map.put("sum10",budget.getAll104());
                    break;
                case 11:
                    map.put("month11",11);
                    map.put("sx11",budget.getSan114());
                    map.put("xg11",budget.getXu114());
                    map.put("sum11",budget.getAll114());
                    break;
                case 12:
                    map.put("month12",12);
                    map.put("sx12",budget.getSan124());
                    map.put("xg12",budget.getXu124());
                    map.put("sum12",budget.getAll124());
                    break;
            }
        }
    }

    private LinkedHashMap<String,Object> filterData(Integer startMonth, Integer endMonth, YsBudgetBO budgetBO){
        LinkedHashMap<String,Object> map = new LinkedHashMap<>();
        map.put("subjectCode", budgetBO.getSubjectCode());
        map.put("subjectName",budgetBO.getSubjectName());
        map.put("departmentName",budgetBO.getDepartmentName());
        selectMonth(startMonth,endMonth,map,budgetBO);
        map.put("sxTotal",budgetBO.getSan134()==null ? BigDecimal.ZERO:budgetBO.getSan134());
        map.put("xgTotal",budgetBO.getXu134()==null ?BigDecimal.ZERO:budgetBO.getXu134());
        map.put("total",budgetBO.getAll134()==null?BigDecimal.ZERO:budgetBO.getAll134());
        return map;
    }
    private List<AccountHeaderVO> generateTableHeader(Integer startMonth, Integer endMonth){
        //构建表头
        List<AccountHeaderVO> tableHeader = new ArrayList<>();
        for(int i=startMonth;i<=endMonth;i++){
            switch (i){
                case 1:
                    tableHeader.add(AccountHeaderVO.builder().month("1月").he("sum1").xu("xg1").sa("sx1")
                            .build());
                    break;
                case 2:
                    tableHeader.add(AccountHeaderVO.builder().month("2月").he("sum2").xu("xg2").sa("sx2")
                            .build());
                    break;
                case 3:
                    tableHeader.add(AccountHeaderVO.builder().month("3月").he("sum3").xu("xg3").sa("sx3")
                            .build());
                    break;
                case 4:
                    tableHeader.add(AccountHeaderVO.builder().month("4月").he("sum4").xu("xg4").sa("sx4")
                            .build());
                    break;
                case 5:
                    tableHeader.add(AccountHeaderVO.builder().month("5月").he("sum5").xu("xg5").sa("sx5")
                            .build());
                    break;
                case 6:
                    tableHeader.add(AccountHeaderVO.builder().month("6月").he("sum6").xu("xg6").sa("sx6")
                            .build());
                    break;
                case 7:
                    tableHeader.add(AccountHeaderVO.builder().month("7月").he("sum7").xu("xg7").sa("sx7")
                            .build());
                    break;
                case 8:
                    tableHeader.add(AccountHeaderVO.builder().month("8月").he("sum8").xu("xg8").sa("sx8")
                            .build());
                    break;
                case 9:
                    tableHeader.add(AccountHeaderVO.builder().month("9月").he("sum9").xu("xg9").sa("sx9")
                            .build());
                    break;
                case 10:
                    tableHeader.add(AccountHeaderVO.builder().month("10月").he("sum10").xu("xg10").sa("sx10")
                            .build());
                    break;
                case 11:
                    tableHeader.add(AccountHeaderVO.builder().month("11月").he("sum11").xu("xg11").sa("sx11")
                            .build());
                    break;
                case 12:
                    tableHeader.add(AccountHeaderVO.builder().month("12月").he("sum12").xu("xg12").sa("sx12")
                            .build());
                    break;
            }
        }
        return tableHeader;
    }

    private List<BigDecimal> sum(Integer month,List<LinkedHashMap<String,Object>> tableData){
        BigDecimal sx_sum = BigDecimal.ZERO;
        BigDecimal xg_sum = BigDecimal.ZERO;
        for (LinkedHashMap<String,Object> t:tableData){
            sx_sum = sx_sum.add(t.get("sx"+month) ==null ? BigDecimal.ZERO:(BigDecimal) t.get("sx"+month));
            xg_sum = xg_sum.add(t.get("xg"+month) ==null ? BigDecimal.ZERO:(BigDecimal) t.get("xg"+month));
        }
        List<BigDecimal> list = new ArrayList<>();
        list.add(sx_sum);
        list.add(xg_sum);
        list.add(sx_sum.add(xg_sum));
        return list;
    }
    private LinkedHashMap<String, BigDecimal> calculate(List<LinkedHashMap<String,Object>> tableData,Integer start,Integer end){
        LinkedHashMap<String, BigDecimal> map = new LinkedHashMap<>();
        for(int i=start;i<=end;i++){
            List<BigDecimal> list = sum(i,tableData);
            switch (i){
                case 1:
                    map.put("sx1",list.get(0));
                    map.put("xg1",list.get(1));
                    map.put("sum1",list.get(2));
                    break;
                case 2:
                    map.put("sx2",list.get(0));
                    map.put("xg2",list.get(1));
                    map.put("sum2",list.get(2));
                    break;
                case 3:
                    map.put("sx3",list.get(0));
                    map.put("xg3",list.get(1));
                    map.put("sum3",list.get(2));
                    break;
                case 4:
                    map.put("sx4",list.get(0));
                    map.put("xg4",list.get(1));
                    map.put("sum4",list.get(2));
                    break;
                case 5:
                    map.put("sx5",list.get(0));
                    map.put("xg5",list.get(1));
                    map.put("sum5",list.get(2));
                    break;
                case 6:
                    map.put("sx6",list.get(0));
                    map.put("xg6",list.get(1));
                    map.put("sum6",list.get(2));
                    break;
                case 7:
                    map.put("sx7",list.get(0));
                    map.put("xg7",list.get(1));
                    map.put("sum7",list.get(2));
                    break;
                case 8:
                    map.put("sx8",list.get(0));
                    map.put("xg8",list.get(1));
                    map.put("sum8",list.get(2));
                    break;
                case 9:
                    map.put("sx9",list.get(0));
                    map.put("xg9",list.get(1));
                    map.put("sum9",list.get(2));
                    break;
                case 10:
                    map.put("sx10",list.get(0));
                    map.put("xg10",list.get(1));
                    map.put("sum10",list.get(2));
                    break;
                case 11:
                    map.put("sx11",list.get(0));
                    map.put("xg11",list.get(1));
                    map.put("sum11",list.get(2));
                    break;
                case 12:
                    map.put("sx12",list.get(0));
                    map.put("xg12",list.get(1));
                    map.put("sum12",list.get(2));
                    break;
            }
        }
        BigDecimal sx_year_sum = BigDecimal.ZERO;
        BigDecimal xg_year_sum = BigDecimal.ZERO;
        BigDecimal all_year_sum = BigDecimal.ZERO;
        for (LinkedHashMap<String,Object> t:tableData){
            sx_year_sum = sx_year_sum.add(t.get("sxTotal") ==null ? BigDecimal.ZERO: (BigDecimal) t.get("sxTotal"));
            xg_year_sum = xg_year_sum.add(t.get("xgTotal") ==null ? BigDecimal.ZERO: (BigDecimal) t.get("xgTotal"));
            all_year_sum = all_year_sum.add(t.get("total") ==null ? BigDecimal.ZERO: (BigDecimal) t.get("total"));
        }
        map.put("sxTotal",sx_year_sum);
        map.put("xgTotal",xg_year_sum);
        map.put("total",all_year_sum);
        return map;
    }
    /*查询业务预算下达数据
    *
    * */
    @Override
    public BudgetRelease business(BudgetDTO dto) {
        Optional.ofNullable(dto.getStartTime())
                .orElseThrow(()->new RuntimeException("起始时间不能为空"));
        Optional.ofNullable(dto.getEndTime())
                .orElseThrow(()->new RuntimeException("截止时间不能为空"));
        Optional.ofNullable(dto.getNum())
                .orElseThrow(()->new RuntimeException("页码为空"));
        Optional.ofNullable(dto.getSize())
                .orElseThrow(()->new RuntimeException("页大小为空"));
        String [] st = dto.getStartTime().split("-");
        String [] end = dto.getEndTime().split("-");
        if(!st[0].equals(end[0])){
            throw  new RuntimeException("年份不能跨越");
        }
        dto.setYear(Integer.valueOf(st[0]));
        dto.setStart(Integer.valueOf(st[1]));
        dto.setEnd(Integer.valueOf(end[1]));
        // 部门隔离
        BdSysUser user = userMapper.getUserById(HttpUtil.getRequestHeaderInfo(Constants.USER_ID));
        // todo  临时权限
        if (!"ALL".equals(user.getDeptCode())){
            dto.setDeptCode(user.getDeptCode());
        }

        //过滤数据
        List<YsBudgetBO> budgetBOList = mapper.getAllBusiness(dto);//获取所有当前年的数据

        List<LinkedHashMap<String,Object>> tableData = new ArrayList<>();
        budgetBOList.forEach(t->{
            tableData.add(filterData(dto.getStart(), dto.getEnd(), t));
        });

        PageInfo<LinkedHashMap<String,Object>> pageInfo = PageHelperTool.excutePageInfo(tableData,dto.getNum(),dto.getSize());

        //构建表头
        List<AccountHeaderVO> tableHeader = generateTableHeader(dto.getStart(),dto.getEnd());

        //构建合计数据
        LinkedHashMap<String,BigDecimal> tableSum = calculate(tableData,dto.getStart(),dto.getEnd());

        BudgetRelease budget = new BudgetRelease();
        budget.setTableHeader(tableHeader);
        budget.setTableData(pageInfo);
        budget.setTableSum(tableSum);
        return budget;
    }

    /*
      导出
    业务预算下达数据
     *
     * */
    @Override
    public void exportExcel1(ExportDTO dto, HttpServletResponse response){
        Optional.ofNullable(dto.getStartTime())
                .orElseThrow(()->new RuntimeException("起始时间不能为空"));
        Optional.ofNullable(dto.getEndTime())
                .orElseThrow(()->new RuntimeException("截止时间不能为空"));
        String [] st = dto.getStartTime().split("-");
        String [] end = dto.getEndTime().split("-");
        if(!st[0].equals(end[0])){
            throw  new RuntimeException("年份不能跨越");
        }
        dto.setYear(Integer.valueOf(st[0]));
        excelTransfer.exportExcel(response, mapper.selectAllBusiness(dto.getYear()), "业务预算下达数据", "sheet",
                YsBusinessBudgetRelease.class);
    }
    /*
    导出管理预算下达数据
     * */
    @Override
    public void exportExcel2(ExportDTO dto, HttpServletResponse response) {
        Optional.ofNullable(dto.getStartTime())
                .orElseThrow(()->new RuntimeException("起始时间不能为空"));
        Optional.ofNullable(dto.getEndTime())
                .orElseThrow(()->new RuntimeException("截止时间不能为空"));
        String [] st = dto.getStartTime().split("-");
        String [] end = dto.getEndTime().split("-");
        if(!st[0].equals(end[0])){
            throw  new RuntimeException("年份不能跨越");
        }
        dto.setYear(Integer.valueOf(st[0]));
        List<YsBusinessBudgetRelease> list = mapper.selectAllManage(dto.getYear());

        Map<String,YsBusinessBudgetRelease> map = new HashMap<>();
        //二次过滤
        list.forEach(t->{
            if(map.containsKey(t.getSubjectName())){
                YsBusinessBudgetRelease manage = map.get(t.getSubjectName());
                manage.setDepartmentName(manage.getDepartmentName()+","+t.getDepartmentName());
                manage.setDepartmentCode(manage.getDepartmentCode()+","+t.getDepartmentCode());
                map.put(manage.getSubjectName(),manage);
            }else{
                map.put(t.getSubjectName(),t);
            }
        });
        excelTransfer.exportExcel(response, new ArrayList<>(map.values()), "管理预算下达数据", "sheet",
                YsBusinessBudgetRelease.class);

    }




}
